#include<string>
#include<Windows.h>
#include <stdint.h>
#include <iostream>
#include<fstream>
#pragma once

/*
功能：
    记录事件编号
    确定当前回合事件是否生效
    实现事件逻辑
*/
extern class Event {
public:
    int event_time;//记录事件生效时间 1：立即生效 2：回合开始时生效
    int event_id;//记录事件编号
    std::string event_name;//记录事件名
    /*
    功能：
        实现事件逻辑
    参数：
        触发的玩家id
    返回值：
        无
    */
    virtual void EventFun(int);
    /*
    功能：
        确定当前回合事件是否生效
    参数：
        当前回合数
    返回值：
        true为生效
        false为未生效
    */
    bool Check(int);
};


/*
功能：
    记录道具编号
    实现道具逻辑
*/
extern class Loot {
public:
    int loot_time;//记录道具生效时间 1：立即生效 2：回合开始时生效
    int loot_id;//记录道具id
    std::string loot_name;//记录道具名
    /*
    功能：
        实现道具逻辑
    参数：
        触发的玩家id
    返回值：
        无
    */
    virtual void LootFun(int);
};



extern int Round;//总回合数
extern int now_round;//当前回合数
extern Event** event_queue ;//进入生效队列的事件全局事件


/*
功能：
    结构体Point用来记录当前光标的x,y坐标
*/
extern struct Point {
    short x, y;
};


/*
功能：
   记录玩家信息
*/
extern struct Player {
    int player_id;//玩家编号
    std::string name;//玩家名
    int character_id;//使用角色id
    int mp_locat;//记录玩家位置
    int star_num;//记录玩家拥有的星星数
    int step;//记录玩家走过的步数
    Loot* loots[20];//记录玩家所有拥有的道具
    Event* event_queue[20];//进入生效队列的事件
    Loot* loot_queue[20];//进入生效队列的道具
  
};
extern Player player[4];//所有玩家的集合


/*
功能：
    储存角色信息
    实现投点功能
    输出背景故事
*/
extern class Character {
public:
    Character(int m_id);
    void setdice();//双生子和破败王更改色子用
    int id;//角色编号
    std::string character_name;//角色名
    std::string backstory;//背景故事描述
    int dice[10];
    bool choose;//角色是否被选中
    //模拟投点 返回值为点数
    int Roll();
    //输出背景故事
    void PrintBackstory();
};

extern Character** chara;//所有角色的集合 下标和id相同

/*
功能：
    记录地图位置 编号 事件
*/
extern class Map {
public:
    Point a, b;//记录地图块位置 其中a为x,y偏小的那个坐标 b为x,y偏大的那个坐标
    int map_id;//记录地图块编号
    Event* event_id;//指向设置的事件
    bool star;//记录是否存在星星 true为存在false为不存在
    bool crossing;//记录是否是岔路 true为是false为不是
    int nex_id1, nex_id2;//id1为无岔路时下一个格子编号，id2为有岔路格子的第二条路的格子编号。
    int come;//上一个格子编号
    Map(int id, Event* e_id, bool cross, int id1, int id2, int la_id, int x1, int y1, int x2, int y2)
        //参数分别为：地图编号，事件id，是否岔路，下一个格子编号，有岔路的另一个格子编号,(x1,y1)(x2,y2)为a b的值即格子坐标
    {
        this->star = 0;
        this->map_id = id;
        this->crossing = cross;
        this->event_id = e_id;
        this->nex_id1 = id1;
        this->nex_id2 = id2;
        this->come = la_id;
        this->a.x = x1;
        this->a.y = y1;
        this->b.x = x2;
        this->b.y = y2;
    }
};

extern Map** mp ;//所有地图块的集合






//---------------------------------view-------------------------------------

/*
功能：
    参考墨刀原型图打印开始菜单
    实现光标移动选中的文字高亮显示
    在用户按下回车键后可以跳转到相应界面
    跳转入排行榜界面时传入参数0
参数：无
返回值：无
*/
void ShowBeginPage();


/*
功能：
    参考墨刀原型图打印人物选择界面
    实现光标移动选中的文字高亮显示
    首先进行玩家名字输入
    接着进行人物选择
    在光标移动到对应人物上时 人物介绍框刷新出对应人物的背景故事和骰子种类
    按回车键进行选择
    人物选择后进行游戏回合数选择
    选择结束后光标移动到开始游戏上
    按开始游戏后进入游戏界面
参数：无
返回值：无
*/
int ShowCharacterPage(int n, Character* cha[]);


/*
功能：
    参考墨刀原型图打印游戏界面
    打印地图和角色信息
    将游戏提示信息打印在行动记录框里
    调用游戏运行程序
    跳转至排行榜界面并传入参数1
参数：无
返回值：无
*/
void ShowGamePage();


/*
功能：
    调用Rank()函数获取最近一次排行写入历史文件*dao*
    参考墨刀原型图打印排行榜界面
    若是传入参数为1表示是从游戏界面跳转而来 显示是否再来一局
    选择是跳转至游戏开始界面 选择否结束函数
    若是传入参数为0表示是从开始菜单界面跳转而来 显示返回按钮
    使用返回按钮可以跳转至游戏开始菜单
参数：判断跳转来源
返回值：无
*/
void ShowRankPage(int);

//--------------------------------service--------------------------------------
inline void gotoxy(short x, short y) {                   //设置光标位置
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), { x, y });
}
inline void setcolor(int a)                               //设置打印颜色
{
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), a);
}

/*
功能：
    实现光标移动和文字高亮显示
参数：
    结构体a储存当前光标位置
    结构体b储存目标光标位置
    c表示当前光标指向的文字内容
    d表示目标光标指向的文字内容
    x表示当前字体的颜色
    y表示需要高亮后的颜色
返回值：
    无
*/
inline void MoveCursor(Point a, Point b, std::string c, std::string d, int x, int y) {
    gotoxy(a.x, a.y);
    setcolor(x);
    std::cout << c;
    gotoxy(b.x, b.y);
    setcolor(y);
    std::cout << d;
    gotoxy(b.x, b.y);
    setcolor(x);
}




/*
功能：
    游戏运行
    调用生成星星函数生成一颗星星
    各玩家分别投点 按大小决定回合内行动顺序
    在全局事件队列中加入对应全局事件
    *循环*
       扫描全局事件队列 将本回合生效的事件弹出并生效
       扫描当前玩家的事件生效队列和道具生效队列将回合开始时生效的事件和道具弹出并生效
       判断玩家是否有道具 如有在事件框分别打印出各个道具和跳过选项
       调用PlayerState();维护玩家状态栏
       如使用道具 判断道具生效时间 立即生效就立即生效 否则加入玩家的道具生效队列
       打印提示让玩家按键投点
       投点结果显示在投点显示框
       读取点数进行移动
       每移动一次判断一次是否经过星星或起点
       如有进行相应判断
       移动结束判断地图是否有事件
       如有事件将事件加入事件生效队列
       将队列中立即生效类型的事件拿出来生效
       调用Rank();
       判断是否是本回合最后一个玩家 是就跳出循环 否就继续
    *循环结束*
    局内回合数+1
    判断本局游戏是否结束 否则重复上述循环
    输出胜利提示
    跳转到排行榜界面
    结束函数
参数：无
返回值：无
*/
void GamePlay();


/*
功能：
    生成星星
参数：无
返回值：无
*/
void CreatStar();


/*
功能：
    维护排行榜
    读取全局变量打印排行榜 和当前回合数/总回合数
参数：无
返回值：无
*/
void Rank();


/*
功能：
    维护玩家状态栏
    读取玩家当前状态 打印玩家名称 星星数 骰子种类和数目 道具
参数：无
返回值：无
*/
void PlayerState();

/*
功能：
    在地图上移动
    判断当前是否是岔路
参数：当前地图编号
返回值：无
*/
void MapMove(int& x, bool direction);
void ShowRankPage(int source);
void inputPlayerNamePage();//玩家信息
void ShowSettingPage();//设置界面







inline void init()//初始化的函数(角色，地图)
{
    for (int i = 1; i < 10; i++)//角色初始化
    {
        chara[i] = new Character(i);

    }
    for(int i=1;i<9;i++)
    { 
    event_queue[i]=new Event;
    event_queue[i]->event_id = 1;
   }
    mp[0] = new Map(0, event_queue[5], 0, 1, 0, 74, 111, 30, 116, 33);
    mp[1] = new Map(1, NULL, 0, 2, 0, 0, 111, 27, 116, 30);
    mp[2] = new Map(2, NULL, 0, 3, 0, 1, 111, 24, 116, 27);
    mp[3] = new Map(3, NULL, 0, 4, 0, 2, 111, 21, 116, 24);
    mp[4] = new Map(4, NULL, 0, 5, 0, 3, 111, 18, 116, 21);
    mp[5] = new Map(5, event_queue[2], 0, 6, 0, 4, 111, 15, 116, 18);
    mp[6] = new Map(6, NULL, 0, 7, 0, 5, 111, 12, 116, 15);
    mp[7] = new Map(7, event_queue[3], 0, 8, 0, 6, 106, 12, 111, 15);
    mp[8] = new Map(8, NULL, 0, 9, 0, 7, 101, 12, 106, 15);
    mp[9] = new Map(9, event_queue[4], 0, 10, 0, 8, 96, 12, 101, 15);
    mp[10] = new Map(10, NULL, 0, 11, 0, 9, 91, 12, 96, 15);
    mp[11] = new Map(11, event_queue[3], 0, 12, 0, 10, 86, 12, 91, 15);
    mp[12] = new Map(12, event_queue[1], 0, 13, 0, 11, 81, 12, 86, 15);
    mp[13] = new Map(13, event_queue[6], 1, 14, 29, 12, 81, 15, 86, 18);
    mp[14] = new Map(14, NULL, 0, 15, 0, 13, 76, 15, 81, 18);
    mp[15] = new Map(15, NULL, 0, 16, 0, 14, 71, 15, 76, 18);
    mp[16] = new Map(16, event_queue[4], 0, 17, 0, 15, 66, 15, 71, 18);
    mp[17] = new Map(17, NULL, 0, 18, 0, 16, 61, 15, 66, 18);
    mp[18] = new Map(18, event_queue[1], 0, 19, 0, 17, 56, 15, 61, 18);
    mp[19] = new Map(19, event_queue[3], 0, 20, 0, 18, 56, 18, 61, 21);
    mp[20] = new Map(20, event_queue[4], 0, 21, 0, 19, 56, 21, 61, 24);
    mp[21] = new Map(21, event_queue[3], 0, 22, 0, 20, 56, 24, 61, 27);
    mp[22] = new Map(22, event_queue[7], 0, 23, 0, 21, 56, 27, 61, 30);
    mp[23] = new Map(23, event_queue[2], 0, 24, 0, 22, 56, 30, 61, 33);
    mp[24] = new Map(24, event_queue[6], 1, 45, 25, 23, 61, 30, 66, 33);
    mp[25] = new Map(25, event_queue[6], 1, 35, 26, 24, 66, 30, 71, 33);
    mp[26] = new Map(26, event_queue[6], 1, 27, 66, 25, 71, 30, 76, 33);
    mp[27] = new Map(27, NULL, 0, 28, 0, 26, 76, 30, 81, 33);
    mp[28] = new Map(28, NULL, 0, 38, 0, 27, 81, 30, 86, 33);
    mp[29] = new Map(29, NULL, 0, 30, 0, 13, 81, 18, 86, 21);
    mp[30] = new Map(30, event_queue[7], 0, 36, 0, 29, 81, 21, 86, 24);
    mp[31] = new Map(31, NULL, 0, 30, 0, 32, 76, 21, 81, 24);
    mp[32] = new Map(32, event_queue[4], 0, 31, 0, 33, 71, 21, 76, 24);
    mp[33] = new Map(33, event_queue[2], 0, 32, 0, 34, 66, 21, 83, 24);
    mp[34] = new Map(34, NULL, 0, 33, 0, 35, 66, 24, 83, 27);
    mp[35] = new Map(35, NULL, 0, 34, 0, 25, 66, 27, 83, 30);
    mp[36] = new Map(36, NULL, 0, 37, 0, 30, 81, 24, 86, 27);
    mp[37] = new Map(37, event_queue[4], 0, 28, 0, 36, 81, 27, 86, 30);
    mp[38] = new Map(38, event_queue[8], 0, 39, 0, 28, 86, 30, 91, 33);
    mp[39] = new Map(39, NULL, 0, 40, 0, 38, 91, 30, 96, 33);
    mp[40] = new Map(40, NULL, 0, 41, 0, 39, 91, 33, 96, 36);
    mp[41] = new Map(41, NULL, 0, 42, 0, 40, 91, 36, 96, 39);
    mp[42] = new Map(42, event_queue[4], 0, 43, 0, 41, 91, 39, 96, 42);
    mp[43] = new Map(43, NULL, 0, 44, 0, 42, 91, 42, 96, 45);
    mp[44] = new Map(44, NULL, 0, 67, 0, 56, 91, 45, 96, 48);
    mp[45] = new Map(45, NULL, 0, 46, 0, 24, 61, 33, 66, 36);
    mp[46] = new Map(46, event_queue[3], 0, 47, 0, 45, 61, 36, 66, 39);
    mp[47] = new Map(47, event_queue[6], 1, 48, 65, 46, 61, 39, 66, 42);
    mp[48] = new Map(48, NULL, 0, 49, 0, 47, 61, 42, 66, 45);
    mp[49] = new Map(49, event_queue[3], 0, 50, 0, 48, 61, 42, 66, 45);
    mp[50] = new Map(50, event_queue[2], 0, 51, 0, 49, 61, 45, 66, 48);
    mp[51] = new Map(51, event_queue[8], 0, 52, 0, 50, 66, 45, 71, 48);
    mp[52] = new Map(52, NULL, 0, 53, 0, 51, 71, 45, 76, 48);
    mp[53] = new Map(53, event_queue[3], 0, 54, 0, 52, 76, 45, 86, 48);
    mp[54] = new Map(54, event_queue[2], 0, 55, 0, 53, 81, 45, 91, 48);
    mp[55] = new Map(55, NULL, 0, 56, 0, 54, 86, 45, 91, 48);
    mp[56] = new Map(56, NULL, 0, 44, 0, 55, 91, 45, 96, 48);
    mp[57] = new Map(57, event_queue[7], 0, 55, 0, 55, 81, 42, 91, 45);
    mp[58] = new Map(58, NULL, 0, 57, 0, 57, 81, 39, 91, 42);
    mp[59] = new Map(59, event_queue[6], 1, 58, 60, 61, 81, 36, 91, 39);
    mp[60] = new Map(60, NULL, 0, 41, 0, 59, 86, 36, 96, 39);
    mp[61] = new Map(61, NULL, 0, 59, 0, 62, 76, 36, 86, 39);
    mp[62] = new Map(62, NULL, 0, 61, 0, 63, 71, 36, 81, 39);
    mp[63] = new Map(63, event_queue[6], 1, 64, 62, 65, 71, 39, 81, 42);
    mp[64] = new Map(64, NULL, 0, 53, 0, 63, 76, 42, 86, 45);
    mp[65] = new Map(65, NULL, 0, 63, 0, 47, 66, 39, 76, 42);
    mp[66] = new Map(66, NULL, 0, 62, 0, 62, 71, 33, 81, 33);
    mp[67] = new Map(67, event_queue[2], 0, 68, 0, 44, 96, 45, 101, 48);
    mp[68] = new Map(68, NULL, 0, 69, 0, 67, 101, 45, 106, 48);
    mp[69] = new Map(69, event_queue[6], 1, 70, 79, 68, 106, 45, 111, 48);
    mp[70] = new Map(70, NULL, 0, 71, 0, 69, 106, 42, 111, 45);
    mp[71] = new Map(71, NULL, 0, 72, 0, 70, 106, 39, 111, 42);
    mp[72] = new Map(72, event_queue[6], 1, 75, 73, 71, 106, 36, 111, 39);
    mp[73] = new Map(73, NULL, 0, 74, 0, 72, 111, 36, 116, 39);
    mp[74] = new Map(74, NULL, 0, 0, 0, 73, 111, 33, 116, 36);
    mp[75] = new Map(75, NULL, 0, 76, 0, 72, 101, 36, 106, 39);
    mp[76] = new Map(76, NULL, 0, 77, 0, 75, 101, 33, 106, 36);
    mp[77] = new Map(77, event_queue[4], 0, 78, 0, 76, 101, 30, 106, 33);
    mp[78] = new Map(78, NULL, 0, 0, 0, 77, 106, 30, 111, 33);
    mp[79] = new Map(79, NULL, 0, 80, 0, 69, 111, 45, 116, 48);
    mp[80] = new Map(80, NULL, 0, 81, 0, 79, 116, 45, 121, 48);
    mp[81] = new Map(81, NULL, 0, 82, 0, 80, 121, 45, 126, 48);
    mp[82] = new Map(82, NULL, 0, 83, 0, 81, 121, 42, 126, 45);
    mp[83] = new Map(82, event_queue[8], 0, 83, 0, 82, 121, 39, 126, 42);
    mp[84] = new Map(84, NULL, 0, 84, 0, 83, 121, 36, 126, 39);
    mp[85] = new Map(85, event_queue[7], 0, 85, 0, 84, 121, 33, 126, 36);
    mp[86] = new Map(86, event_queue[1], 0, 86, 0, 85, 121, 30, 126, 33);
    mp[87] = new Map(87, NULL, 0, 87, 0, 86, 116, 30, 121, 33);
}